pub mod connection;
pub mod message;
pub mod channel;

use ws;

use std;
use std::thread::spawn;
use std::sync::mpsc;
use std::net::SocketAddr;

use std::thread;
use std::time::Duration;

use ws::{HandshakeError, Error, Result, Message};
use ws::handshake::HandshakeRole;

use mio;
use mio::{Poll, Events, Token, PollOpt, Ready};

use game::message::{ChessCommand, PlayerResponse};

use net::connection::Connections;
use net::channel::Channel;

///server标识
const SERVER: Token = Token(0);

///网络线程
pub fn net_loop(sender: mpsc::SyncSender<message::Message>, receiver: mpsc::Receiver<message::Message>){
    let addr = "127.0.0.1:8020".parse().unwrap();

    let handle = thread::spawn( move ||{
        net_handler(addr, sender, receiver);
    });

//    println!("{:?}", handle.join().unwrap());
}

fn net_handler(addr: SocketAddr, sender: mpsc::SyncSender<message::Message>, receiver: mpsc::Receiver<message::Message>){
    let duration = Some(Duration::from_millis(100));
    let server = mio::net::TcpListener::bind(&addr).unwrap();
    info!("Server start on address: {:?}", addr);
    let poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(64);
    poll.register(&server, SERVER, Ready::readable(), PollOpt::edge()).unwrap();
    let mut connections = Connections::new(sender, receiver);
    info!("Net thread running....................");
    loop{
        poll.poll(&mut events, duration).unwrap();
        for event in events.iter() {
            match event.token() {
                SERVER => {
                    let accept = server.accept_std();
                    match accept {
                        Ok((stream, address)) => {
                            let conn = ws::accept(stream).map_err(must_not_block);
                            if let Ok(socket) = conn {
                                let channel = Channel::new(address, socket);
                                info!("Get an new connection, id: {}", &channel.id());
                                connections.put_channel(channel);
                            }
                        },
                        Err(e) => {info!("Accept connection error! {}", e)}
                    }
                }
                _ => unreachable!(),
            }
        }
        connections.loop_message();
    }
}

fn must_not_block<Role: HandshakeRole>(err: HandshakeError<Role>) -> Error {
    match err {
        HandshakeError::Interrupted(_) => panic!("Bug: blocking socket would block"),
        HandshakeError::Failure(f) => f,
    }
}

//fn handle_client(stream: std::net::TcpStream) -> Result<()> {
//    let mut socket = ws::accept(stream).map_err(must_not_block)?;
//    loop {
//        match socket.read_message()? {
//            msg @ Message::Text(_) |
//            msg @ Message::Binary(_) => {
//                socket.write_message(msg)?;
//            }
//            Message::Ping(_) |
//            Message::Pong(_) => {}
//        }
//    }
//}